package tp.badugi.bot;

import java.util.Arrays;
import java.util.Random;
import java.util.Set;
import java.util.TreeSet;

import tp.badugi.net.GameStatus;
import tp.badugi.net.iRequestListener;

public class BotCalculatedBettingStrategy extends BotCardInformationProvider{
	
	private final int maximalHandValue = 14320;
	
	private int botHandValue;
	
	private double botHumour;
	
	private Random random = new Random();
	
	private long myPotContribution;
	private long moneyAtRoundStart;
	
	private long bettingAmount = 0;
	
	public String chosenAction = "";
	
	public long betAmount = 0;
	
	public void makeAction(GameStatus gameStatus, String[] possibleActions){
		
		this.botHandValue = this.getValueOfCardsInHand(gameStatus.myCards);
		
		this.botHumour = random.nextDouble() * 0.15;
		if(!this.random.nextBoolean()){
			this.botHumour *= -1;
		}
		
	
		 this.myPotContribution = gameStatus.playerPotContributions[gameStatus.myPlayerNumber];
		 this.moneyAtRoundStart = gameStatus.myChipCount + myPotContribution;
			
		this.bettingAmount = this.betAmountFunction(gameStatus.bettingRound, 
													this.moneyAtRoundStart,
													gameStatus.playerPotContributions[gameStatus.myPlayerNumber]);
		
		this.bettingAmount *= ( 1+this.botHumour );
		
		Set<String> possibleActionsSet = new TreeSet<String>(Arrays.asList(possibleActions));
		
		switch(gameStatus.bettingRound){
		
		case 1: this.firstRoundStrategy(possibleActionsSet, gameStatus);
			break;
			
		case 2: this.secondRoundStrategy(possibleActionsSet, gameStatus);
			break;
			
		case 3: this.thirdRoundStrategy(possibleActionsSet, gameStatus);
			break;
			
		case 4: this.fourthRoundStrategy(possibleActionsSet, gameStatus);
			break;
			
		default : System.out.print("[ERROR] bot makeAction: unrecognized betting round");
			break;
		}
		
		switch(this.chosenAction){
		case iRequestListener.ACTION_FOLD : case iRequestListener.ACTION_CHECK :
		case iRequestListener.ACTION_CALL :
				this.betAmount = 0;
			break;
		case iRequestListener.ACTION_BET : this.betAmount = this.bettingAmount;
			break;
		case iRequestListener.ACTION_RAISE : this.betAmount = this.bettingAmount - gameStatus.betAmount;
			break;
		case iRequestListener.ACTION_ALLIN : this.betAmount = gameStatus.myChipCount;
			break;
		default : System.out.println("[ERROR] BotCalculatedBettingStrategy makeAction:\n"
				+ "unidentified action when setting betAmount");
			break;
	}
	}
	
	private void firstRoundStrategy(Set<String> possiblActions, GameStatus gameStatus){
	
		if(this.botHandValue >= 10000){
			if( possiblActions.contains(iRequestListener.ACTION_BET)){
				this.chosenAction = iRequestListener.ACTION_BET;
			}

			else if( possiblActions.contains(iRequestListener.ACTION_RAISE)){
				this.chosenAction = iRequestListener.ACTION_RAISE;
			}
			
			else if( possiblActions.contains(iRequestListener.ACTION_CALL)){
				this.chosenAction = iRequestListener.ACTION_CALL;
			}
			
			else {
				this.chosenAction = iRequestListener.ACTION_ALLIN;
			}
		}
		
		else if(this.botHandValue >= 5000){
			
			if( possiblActions.contains(iRequestListener.ACTION_CHECK)){
				this.chosenAction = iRequestListener.ACTION_CHECK;
			}
			
			else if( possiblActions.contains(iRequestListener.ACTION_CALL)){

				if ( gameStatus.betAmount < 0.2*gameStatus.myChipCount*(1 + this.botHumour)){
					this.chosenAction = iRequestListener.ACTION_CALL;
				}
				
				else {
					this.chosenAction = iRequestListener.ACTION_FOLD;
				}
			}
			
			else if( possiblActions.contains(iRequestListener.ACTION_ALLIN)){
				
				if( gameStatus.myChipCount < 0.20*gameStatus.potSize*(1 + this.botHumour)){
					this.chosenAction = iRequestListener.ACTION_ALLIN;
				}
				
				else {
					this.chosenAction = iRequestListener.ACTION_FOLD;
				}
			}
			
			else {
				this.chosenAction = iRequestListener.ACTION_FOLD;
			}
		}
		
		else if(this.botHandValue >= 1500){
			if( possiblActions.contains(iRequestListener.ACTION_CHECK)){
				this.chosenAction = iRequestListener.ACTION_CHECK;
			}
			
			else if( possiblActions.contains(iRequestListener.ACTION_CALL)){

				if ( gameStatus.betAmount < 0.15*this.moneyAtRoundStart*(1 + this.botHumour)){
					this.chosenAction = iRequestListener.ACTION_CALL;
				}
				
				else {
					this.chosenAction = iRequestListener.ACTION_FOLD;
				}
			}
			
			else {
				this.chosenAction = iRequestListener.ACTION_FOLD;
			}
		}
		
		else if(this.botHandValue < 1500){
			if( possiblActions.contains(iRequestListener.ACTION_CHECK)){
				this.chosenAction = iRequestListener.ACTION_CHECK;
			}
			
			else if( possiblActions.contains(iRequestListener.ACTION_CALL)){

				if ( gameStatus.betAmount < 0.10*this.moneyAtRoundStart*(1 + this.botHumour)){
					this.chosenAction = iRequestListener.ACTION_CALL;
				}
				
				else {
					this.chosenAction = iRequestListener.ACTION_FOLD;
				}
			}
			
			else {
				this.chosenAction = iRequestListener.ACTION_FOLD;
			}
		}
	}
	
	private void secondRoundStrategy(Set<String> possiblActions, GameStatus gameStatus){
		
		if(this.botHandValue >= 10000){
			if( possiblActions.contains(iRequestListener.ACTION_BET)){
				this.chosenAction = iRequestListener.ACTION_BET;
			}

			else if( possiblActions.contains(iRequestListener.ACTION_RAISE)){
				this.chosenAction = iRequestListener.ACTION_RAISE;
			}
			
			else if( possiblActions.contains(iRequestListener.ACTION_CALL)){
				this.chosenAction = iRequestListener.ACTION_CALL;
			}
			
			else {
				this.chosenAction = iRequestListener.ACTION_ALLIN;
			}
		}
		
		else if(this.botHandValue >= 5000){
			if( possiblActions.contains(iRequestListener.ACTION_CHECK)){
				this.chosenAction = iRequestListener.ACTION_CHECK;
			}
			
			else if( possiblActions.contains(iRequestListener.ACTION_CALL)){

				if ( gameStatus.betAmount < 0.2*gameStatus.myChipCount*(1 + this.botHumour)){
					this.chosenAction = iRequestListener.ACTION_CALL;
				}
				
				else {
					this.chosenAction = iRequestListener.ACTION_FOLD;
				}
			}
			
			else if( possiblActions.contains(iRequestListener.ACTION_ALLIN)){
				
				if( gameStatus.myChipCount < 0.10*gameStatus.potSize*(1 + this.botHumour)){
					this.chosenAction = iRequestListener.ACTION_ALLIN;
				}
				
				else {
					this.chosenAction = iRequestListener.ACTION_FOLD;
				}
			}
			else {
				this.chosenAction = iRequestListener.ACTION_FOLD;
			}
		}
		
		else if(this.botHandValue >= 1500){
			if( possiblActions.contains(iRequestListener.ACTION_CHECK)){
				this.chosenAction = iRequestListener.ACTION_CHECK;
			}
			
			else if( possiblActions.contains(iRequestListener.ACTION_CALL)){

				if ( gameStatus.betAmount < 0.15*gameStatus.myChipCount*(1 + this.botHumour)){
					this.chosenAction = iRequestListener.ACTION_CALL;
				}
				
				else {
					this.chosenAction = iRequestListener.ACTION_FOLD;
				}
			}
			
			else if( possiblActions.contains(iRequestListener.ACTION_ALLIN)){
				
				if( gameStatus.myChipCount < 0.10*gameStatus.potSize*(1 + this.botHumour)){
					this.chosenAction = iRequestListener.ACTION_ALLIN;
				}
				
				else {
					this.chosenAction = iRequestListener.ACTION_FOLD;
				}
			}
			else {
				this.chosenAction = iRequestListener.ACTION_FOLD;
			}
		}
		
		else if(this.botHandValue >= 200){
			if( possiblActions.contains(iRequestListener.ACTION_CHECK)){
				this.chosenAction = iRequestListener.ACTION_CHECK;
			}
			
			else if( possiblActions.contains(iRequestListener.ACTION_CALL)){

				if ( gameStatus.betAmount < 0.08*gameStatus.myChipCount*(1 + this.botHumour)){
					this.chosenAction = iRequestListener.ACTION_CALL;
				}
				
				else {
					this.chosenAction = iRequestListener.ACTION_FOLD;
				}
			}
			
			else if( possiblActions.contains(iRequestListener.ACTION_ALLIN)){
				
				if( gameStatus.myChipCount < 0.08*gameStatus.potSize*(1 + this.botHumour)){
					this.chosenAction = iRequestListener.ACTION_ALLIN;
				}
				
				else {
					this.chosenAction = iRequestListener.ACTION_FOLD;
				}
			}
			else {
				this.chosenAction = iRequestListener.ACTION_FOLD;
			}
		}
		
		else {
			if( possiblActions.contains(iRequestListener.ACTION_CHECK)){
				this.chosenAction = iRequestListener.ACTION_CHECK;
			}

			else {
				this.chosenAction = iRequestListener.ACTION_FOLD;
			}
		}
	}
	
	private void thirdRoundStrategy(Set<String> possiblActions, GameStatus gameStatus){
				
		if(this.botHandValue >= 10000){
			if( possiblActions.contains(iRequestListener.ACTION_BET)){
				this.chosenAction = iRequestListener.ACTION_BET;
			}

			else if( possiblActions.contains(iRequestListener.ACTION_RAISE)){
				this.chosenAction = iRequestListener.ACTION_RAISE;
			}
			
			else if( possiblActions.contains(iRequestListener.ACTION_CALL)){
				this.chosenAction = iRequestListener.ACTION_CALL;
			}
			
			else {
				this.chosenAction = iRequestListener.ACTION_ALLIN;
			}
		}
		
		else if(this.botHandValue >= 5000){
			
			if( possiblActions.contains(iRequestListener.ACTION_CHECK)){
				this.chosenAction = iRequestListener.ACTION_CHECK;
			}
			
			else if( possiblActions.contains(iRequestListener.ACTION_CALL)){

				if ( gameStatus.betAmount < 0.3*gameStatus.myChipCount*(1 + this.botHumour)){
					this.chosenAction = iRequestListener.ACTION_CALL;
				}
				
				else {
					this.chosenAction = iRequestListener.ACTION_FOLD;
				}
			}
			
			else if( possiblActions.contains(iRequestListener.ACTION_ALLIN)){
				
				if( gameStatus.myChipCount < 0.05*gameStatus.potSize ||
						this.myPotContribution > 0.7*this.moneyAtRoundStart*(1 + this.botHumour)){
					this.chosenAction = iRequestListener.ACTION_ALLIN;
				}
				
				else {
					this.chosenAction = iRequestListener.ACTION_FOLD;
				}
			}
			
			else {
				this.chosenAction = iRequestListener.ACTION_FOLD;
			}
		}
		
		else if(this.botHandValue >= 1500){
			if(possiblActions.contains(iRequestListener.ACTION_CHECK)){
				this.chosenAction = iRequestListener.ACTION_CHECK;
			}
			
			else if( possiblActions.contains(iRequestListener.ACTION_CALL)){
				
				if (	gameStatus.betAmount < 0.2 * gameStatus.potSize
						&& gameStatus.betAmount < ((0.1 * ( 1+ this.botHumour)) * gameStatus.myChipCount) ){
					this.chosenAction = iRequestListener.ACTION_CALL;
				}
				else{
					this.chosenAction = iRequestListener.ACTION_FOLD;
				}
			}
			
			else if( possiblActions.contains(iRequestListener.ACTION_ALLIN)){
				
				if (	gameStatus.betAmount < ((0.2 * ( 1+ this.botHumour)) * gameStatus.myChipCount) 
						|| this.myPotContribution > 0.7 * this.moneyAtRoundStart){
					this.chosenAction = iRequestListener.ACTION_ALLIN;
				}
				else{
					this.chosenAction = iRequestListener.ACTION_FOLD;
				}
			}
			
			else{
				this.chosenAction = iRequestListener.ACTION_FOLD;
			}
		}
		
		else if(this.botHandValue >= 200){

			if(possiblActions.contains(iRequestListener.ACTION_CHECK)){
				this.chosenAction = iRequestListener.ACTION_CHECK;
			}
			
			else if( possiblActions.contains(iRequestListener.ACTION_CALL)){
				
				if (	gameStatus.betAmount < 0.1 * gameStatus.potSize
						&& gameStatus.betAmount < ((0.05 * ( 1+ this.botHumour)) * gameStatus.myChipCount) ){
					this.chosenAction = iRequestListener.ACTION_CALL;
				}
				else{
					this.chosenAction = iRequestListener.ACTION_FOLD;
				}
			}
			
			else if( possiblActions.contains(iRequestListener.ACTION_ALLIN)){
				
				if (	gameStatus.betAmount < ((0.1 * ( 1+ this.botHumour)) * gameStatus.myChipCount) 
						|| this.myPotContribution > 0.9 * this.moneyAtRoundStart){
					this.chosenAction = iRequestListener.ACTION_ALLIN;
				}
				else{
					this.chosenAction = iRequestListener.ACTION_FOLD;
				}
			}
			
			else{
				this.chosenAction = iRequestListener.ACTION_FOLD;
			}
		}
		
		else {
			if( possiblActions.contains(iRequestListener.ACTION_CHECK)){
				this.chosenAction = iRequestListener.ACTION_CHECK;
			}

			else {
				this.chosenAction = iRequestListener.ACTION_FOLD;
			}
		}
	}
	
	private void fourthRoundStrategy(Set<String> possiblActions, GameStatus gameStatus){
		
		if(this.botHandValue >= 13000){
			this.chosenAction = iRequestListener.ACTION_ALLIN;
		}
		
		else if(this.botHandValue >= 10000){
			
			if( possiblActions.contains(iRequestListener.ACTION_BET)){
				this.chosenAction = iRequestListener.ACTION_BET;
			}

			else if( possiblActions.contains(iRequestListener.ACTION_RAISE)){
				this.chosenAction = iRequestListener.ACTION_RAISE;
			}
			
			else if( possiblActions.contains(iRequestListener.ACTION_CHECK)){
				this.chosenAction = iRequestListener.ACTION_CHECK;
			}
			
			else if( possiblActions.contains(iRequestListener.ACTION_CALL)){
				this.chosenAction = iRequestListener.ACTION_CALL;
			}
			else {
				this.chosenAction = iRequestListener.ACTION_ALLIN;
			}
		}
		
		else if(this.botHandValue >= 5000){
			if( possiblActions.contains(iRequestListener.ACTION_CHECK)){
				this.chosenAction = iRequestListener.ACTION_CHECK;
			}
			
			else if( possiblActions.contains(iRequestListener.ACTION_CALL)){

				if ( gameStatus.betAmount <= this.bettingAmount
						|| (gameStatus.betAmount < 1.3*this.bettingAmount
						&& this.myPotContribution > 0.20*this.moneyAtRoundStart)
						|| (gameStatus.betAmount < 2*this.bettingAmount
								&& this.myPotContribution > 0.5*this.moneyAtRoundStart)){
					this.chosenAction = iRequestListener.ACTION_CALL;
				}
				
				else {
					this.chosenAction = iRequestListener.ACTION_FOLD;
				}
			}
			
			else if( possiblActions.contains(iRequestListener.ACTION_ALLIN)){
				if ( this.myPotContribution > 0.7*this.moneyAtRoundStart){
					this.chosenAction = iRequestListener.ACTION_ALLIN;
				}
				else{
					this.chosenAction = iRequestListener.ACTION_FOLD;
				}
			}
		}
		
		else if(this.botHandValue >= 1500){
			
			if(possiblActions.contains(iRequestListener.ACTION_CHECK)){
				this.chosenAction = iRequestListener.ACTION_CHECK;
			}
			
			else if( possiblActions.contains(iRequestListener.ACTION_CALL)){
				
				if (	gameStatus.betAmount < 0.2 * gameStatus.potSize
						&& gameStatus.betAmount < ((0.1 * ( 1+ this.botHumour)) * gameStatus.myChipCount) ){
					this.chosenAction = iRequestListener.ACTION_CALL;
				}
				else{
					this.chosenAction = iRequestListener.ACTION_FOLD;
				}
			}
			
			else if( possiblActions.contains(iRequestListener.ACTION_ALLIN)){
				
				if (	gameStatus.betAmount < ((0.2 * ( 1+ this.botHumour)) * gameStatus.myChipCount) 
						|| this.myPotContribution > 0.7 * this.moneyAtRoundStart){
					this.chosenAction = iRequestListener.ACTION_ALLIN;
				}
				else{
					this.chosenAction = iRequestListener.ACTION_FOLD;
				}
			}
			
			else{
				this.chosenAction = iRequestListener.ACTION_FOLD;
			}
		}
		
		else if(this.botHandValue >= 500){

			if(possiblActions.contains(iRequestListener.ACTION_CHECK)){
				this.chosenAction = iRequestListener.ACTION_CHECK;
			}
			
			else if( possiblActions.contains(iRequestListener.ACTION_CALL)){
				
				if (	gameStatus.betAmount < 0.1 * gameStatus.potSize
						&& gameStatus.betAmount < ((0.05 * ( 1+ this.botHumour)) * gameStatus.myChipCount) ){
					this.chosenAction = iRequestListener.ACTION_CALL;
				}
				else{
					this.chosenAction = iRequestListener.ACTION_FOLD;
				}
			}
			
			else if( possiblActions.contains(iRequestListener.ACTION_ALLIN)){
				
				if (	gameStatus.betAmount < ((0.1 * ( 1+ this.botHumour)) * gameStatus.myChipCount) 
						|| this.myPotContribution > 0.9 * this.moneyAtRoundStart){
					this.chosenAction = iRequestListener.ACTION_ALLIN;
				}
				else{
					this.chosenAction = iRequestListener.ACTION_FOLD;
				}
			}
			
			else{
				this.chosenAction = iRequestListener.ACTION_FOLD;
			}
		}
		
		else if(this.botHandValue >= 200){
			if(possiblActions.contains(iRequestListener.ACTION_CHECK)){
				this.chosenAction = iRequestListener.ACTION_CHECK;
			}
			
			else if( possiblActions.contains(iRequestListener.ACTION_CALL)){
				
				if (	gameStatus.betAmount < 0.05 * gameStatus.potSize
						&& gameStatus.betAmount < ((0.02 * ( 1+ this.botHumour)) * gameStatus.myChipCount) ){
					this.chosenAction = iRequestListener.ACTION_CALL;
				}
				else{
					this.chosenAction = iRequestListener.ACTION_FOLD;
				}
			}
			
			else if( possiblActions.contains(iRequestListener.ACTION_ALLIN)){
				
				if (	gameStatus.betAmount < ((0.05 * ( 1+ this.botHumour)) * gameStatus.myChipCount) 
						|| this.myPotContribution > 0.95 * this.moneyAtRoundStart){
					this.chosenAction = iRequestListener.ACTION_ALLIN;
				}
				else{
					this.chosenAction = iRequestListener.ACTION_FOLD;
				}
			}
			
			else{
				this.chosenAction = iRequestListener.ACTION_FOLD;
			}
		}
			
		else {
			if( possiblActions.contains(iRequestListener.ACTION_CHECK)){
				this.chosenAction = iRequestListener.ACTION_CHECK;
			}

			else {
				this.chosenAction = iRequestListener.ACTION_FOLD;
			}
		}
	}
	
	private long betAmountFunction(int bettingRound,
			long chipCountWhenRoundStarted, long chipsUsedInRound){
		
		long bet = 0;
		
		double roundRatio = (double)bettingRound/(double)4;
		
		double handRatio = (double)this.botHandValue/(double)this.maximalHandValue;
		
		long betToThatRound = (long)(chipCountWhenRoundStarted * handRatio * roundRatio);
		
		bet = betToThatRound - chipsUsedInRound;
		
		return bet;
	}
}
